﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MonsterBehaviorModeBest<BehaviorScoreModeType> : MonsterBehaviorMode
    where BehaviorScoreModeType : MonsterBehaviorScoreMode
{
    //怪物感应到玩家存在的一个范围
    [SerializeField] protected float hunchRangeRadius;

    //怪物的攻击范围
    [SerializeField] protected float attackRangeRadius;

    protected Monster monster;
    protected BehaviorScoreModeType behaviorScoreMode;


    protected virtual void Awake()
    {
        monster = GetComponent<Monster>();
        behaviorScoreMode = GetComponent<BehaviorScoreModeType>();
    }


    public override void Operation()
    {
        behaviorScoreMode.GetBehavior()();
    }


    public override void IdleBehavior()
    {
        MonsterTaskProcessor.Instance.AddTaskBack(new MonsterTaskIdle(monster,()=> { return GetTargetPlayer() != null; }, 2.0f));
    }


    public override void WalkBehavior()
    {
        Vector3 ramHorizontal = UnityEngine.Random.Range(0, 2) > 0 ? Vector3.left : Vector3.right;
        MonsterTaskProcessor.Instance.AddTaskBack(new MonsterTaskHorizontalWalk(monster, () => { return GetTargetPlayer() != null; }, ramHorizontal, 10));
    }



    public override void RunBehavior()
    {
        GameObject target = GetTargetPlayer();
        if (target == null)
        {
            return;
        }

        Vector3 horizontal = Vector3.zero;
        if (target.transform.position.x < transform.position.x)
        {
            horizontal = Vector3.left;
        }
        else if (target.transform.position.x > transform.position.x)
        {
            horizontal = Vector3.right;
        }

        float distance = Mathf.Abs(target.transform.position.x - transform.position.x);
        MonsterTaskProcessor.Instance.AddTaskBack(new MonsterTaskHorizontalRun(monster,()=> { return GetAttackTargetPlayer() != null; }, horizontal, distance));
    }



    public override void JumpBehavior()
    {
        GameObject target = GetTargetPlayer();
        if (target == null)
        {
            return;
        }

        if (transform.position.y < target.transform.position.y)
        {
            MonsterTaskProcessor.Instance.AddTaskBack(new MonsterTaskVerticalMove(monster, Vector3.up, monster.jumpHigh));
        }
        Debug.Log("Jump");
    }


    public override void NormalAttackBehavior()
    {
        GameObject target = GetAttackTargetPlayer();
        if (target != null)
        {
            MonsterTaskProcessor.Instance.AddTaskBack(new MonsterTaskNormalAttack(monster, null));
        }
    }


    //获得目标玩家，当同时感应到多个玩家时，该函数能过滤出对于怪物而言最有利的玩家进行处理
    public override GameObject GetTargetPlayer()
    {
        List<GameObject> players = GetHunchRangePlayers(hunchRangeRadius);
        GameObject target = null;

        //当前以距离为基准，对于怪物来说，最近距离的玩家对于它而言接近它是最有利的
        float minDistance = float.MaxValue;
        for (int i = 0; i != players.Count; ++i)
        {
            float temp = Vector3.Distance(players[i].transform.position, transform.position);
            if (target == null || temp < minDistance)
            {
                minDistance = temp;
                target = players[i];
            }
        }

        return target;
    }


    public override GameObject GetAttackTargetPlayer()
    {
        List<GameObject> players = GetHunchRangePlayers(attackRangeRadius);
        GameObject target = null;

        //当前以LP 为基准，对于怪物来说，攻击最低血量的玩家对于它而言是最有利的
        int minLp = int.MaxValue;
        for (int i = 0; i != players.Count; ++i)
        {
            //TODO: 获得玩家当前血量的方法有待修改
            int currLp = players[i].GetComponent<MoreMountains.CorgiEngine.Health>().CurrentHealth;
            if (currLp < minLp)
            {
                minLp = currLp;
                target = players[i];
            }
        }

        return target;
    }



    public override List<GameObject> GetHunchRangePlayers()
    {
        return GetHunchRangePlayers(hunchRangeRadius);
    }



    protected List<GameObject> GetHunchRangePlayers(float checkRange)
    {
        List<GameObject> players = new List<GameObject>();
        Collider2D[] colliders = Physics2D.OverlapCircleAll(transform.position, checkRange);
        for (int i = 0; i != colliders.Length; ++i)
        {
            if (colliders[i].gameObject.tag == GameObjectTags.playerTag)
            {
                players.Add(colliders[i].gameObject);
            }
        }
        return players;
    }
}
